package JUnitTests;

import static org.junit.Assert.*;

import java.util.ArrayList;

import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;

import DataStorageClasses.Reviewer;
import Database.DatabaseConnector;
import ExceptionClasses.InvalidReviewerAuthenticationException;

public class ReviewerConnectorTests 
{
	private static DatabaseConnector dbConnector;
	private static String businessName;
	private static String businessPassword;
	private static String userName;
	private static String email;
	private static String reviewerPassword;
	private static Reviewer reviewer;
	
	@BeforeClass public static void initialize()
	{
		dbConnector = new DatabaseConnector();
		dbConnector.connect();
		
		businessName = "TesterBusiness";
		businessPassword = "password";
		dbConnector.addBusiness(businessName, businessPassword, null, null, null, null, null, null, null, null, null);
		
		userName = "TesterUserName";
		email = "TesterEmail";
		reviewerPassword = "reviwerPassword";
		
		reviewer = dbConnector.addReviewer(userName, reviewerPassword, email);
	}
	
	@AfterClass public static void destroy()
	{
		try {
			dbConnector.removeReviewer(userName, reviewerPassword);
		} catch (InvalidReviewerAuthenticationException e) {
			e.printStackTrace();
		}
		
		dbConnector.removeBusiness(businessName, businessPassword);
		dbConnector.disconnect();
	}
	
	@Test public void testAuthentication()
	{
		String wrongUserName = "wrongUsername123";
		String wrongPassword = "wrongpassword";
		
		boolean authenticated = dbConnector.authenticateReviewer(userName, reviewerPassword);
		assertTrue(authenticated);
		
		authenticated = dbConnector.authenticateReviewer(userName, wrongPassword);
		assertFalse(authenticated);
		
		authenticated = dbConnector.authenticateReviewer(wrongUserName, reviewerPassword);
		assertFalse(authenticated);
	}
	
	@Test public void testAddReviewer()
	{
		assertNotNull(reviewer);
		
		String rev = "reviewer";
		String password = "somepassword";
		String email1 = "someemail";
		
		Reviewer r = dbConnector.addReviewer(userName, reviewerPassword, email);
		assertNull(r);
		
		r = dbConnector.addReviewer(rev, null, email);
		assertNull(r);
		
		r = dbConnector.addReviewer(rev, password, null);
		assertNull(r);
	}
	
	@Test public void testSubscribeToBusiness()
	{
		String invalidUser = "invalidUser";
		String invalidBusiness = "invalidBusiness";
		
		String wrongPassword = "wrongPassword";
		try {
			boolean subscribed = dbConnector.subscribeToBusiness(userName, wrongPassword, businessName);
			fail();
		} 
		catch (InvalidReviewerAuthenticationException e) {
		}
		
		try {
			boolean subscribed = dbConnector.subscribeToBusiness(invalidUser, reviewerPassword, businessName);
			fail();
		} 
		catch (InvalidReviewerAuthenticationException e) {
		}
		
		try {
			boolean subscribed = dbConnector.subscribeToBusiness(userName, reviewerPassword, invalidBusiness);
			assertFalse(subscribed);
		} 
		catch (InvalidReviewerAuthenticationException e) {
		}
		
		try {
			boolean subscribed = dbConnector.subscribeToBusiness(userName, reviewerPassword, businessName);
			assertTrue(subscribed);
		} 
		catch (InvalidReviewerAuthenticationException e) {
		}
		
		try {
			boolean subscribed = dbConnector.subscribeToBusiness(userName, reviewerPassword, businessName);
			assertFalse(subscribed);
		} 
		catch (InvalidReviewerAuthenticationException e) {
		}
		
		try {
			dbConnector.removeSubscription(userName, reviewerPassword, businessName);
		} catch (InvalidReviewerAuthenticationException e) {
			e.printStackTrace();
		}
	}
	
	@Test public void testRemoveSubscription()
	{
		String invalidUser = "invalidUser";
		String invalidBusiness = "invalidBusiness";
		String wrongPassword = "wrongPassword";
		boolean subscribed;
		
		try {
			subscribed = dbConnector.subscribeToBusiness(userName, reviewerPassword, businessName);
			assertTrue(subscribed);
		} 
		catch (InvalidReviewerAuthenticationException e) {
			fail();
		}
		
		try {
			subscribed = dbConnector.removeSubscription(userName, wrongPassword, businessName);
			fail();
		} catch (InvalidReviewerAuthenticationException e) {
		}
		
		try {
			subscribed = dbConnector.removeSubscription(userName, reviewerPassword, businessName);
			assertTrue(subscribed);
		} catch (InvalidReviewerAuthenticationException e) {
			fail();
		}
		
		try {
			subscribed = dbConnector.removeSubscription(userName, reviewerPassword, businessName);
			assertFalse(subscribed);
		} catch (InvalidReviewerAuthenticationException e) {
			fail();
		}
	}
	
	@Test public void testRemove()
	{
		String rev = "reviewer";
		String password = "somepassword";
		String wrongPassword = "wrongPassword";
		String email1 = "someemail";
		boolean removed;
		
		Reviewer r = dbConnector.addReviewer(rev, password, email1);
		assertNotNull(r);
		
		try {
			removed = dbConnector.removeReviewer(rev, wrongPassword);
			fail();
		} catch (InvalidReviewerAuthenticationException e) {
		}
		
		try {
			removed = dbConnector.removeReviewer(rev, password);
			assertTrue(removed);
		} catch (InvalidReviewerAuthenticationException e) {
			fail();
			e.printStackTrace();
		}
		
		r = dbConnector.addReviewer(rev, password, email1);
		assertNotNull(r);
		
		try {
			boolean subscribed = dbConnector.subscribeToBusiness(rev, password, businessName);
			assertTrue(subscribed);
		} catch (InvalidReviewerAuthenticationException e) {
			fail();
		}
		
		try {
			removed = dbConnector.removeReviewer(rev, wrongPassword);
			fail();
		} catch (InvalidReviewerAuthenticationException e) {
			
		}
		
		try {
			removed = dbConnector.removeReviewer(rev, password);
			assertTrue(removed);
		} catch (InvalidReviewerAuthenticationException e) {
			fail();
		}
		
		try {
			removed = dbConnector.removeReviewer(rev, password);
			fail();
		} catch (InvalidReviewerAuthenticationException e) {
		}
	}
	
	@Test public void testEditReviewer()
	{
		String newPassword = "newPassword";
		String wrongPassword = "wrongPassword";
		String newEmail = "newEmail";
		boolean updated;
		
		try {
			updated = dbConnector.editReviewer(userName, wrongPassword, newPassword, newEmail);
			fail();
		} catch (InvalidReviewerAuthenticationException e) {
		}
		
		try {
			updated = dbConnector.editReviewer(userName, reviewerPassword, null, null);
			assertFalse(updated);
		} catch (InvalidReviewerAuthenticationException e) {
			fail();
		}
		
		try {
			updated = dbConnector.editReviewer(userName, reviewerPassword, newPassword, newEmail);
			if(updated) {
				reviewerPassword = newPassword; 
				//find bugs says this is bad, but there wont be multiple instances of this
				email = newEmail;
			}
			else {
				fail();
			}
			
		} catch (InvalidReviewerAuthenticationException e) {
			fail();
		}
		
		updated = dbConnector.authenticateReviewer(userName, newPassword);
		assertTrue(updated);
	}
	
	@Test public void testGetEmail()
	{
		String email1;
		
		email1 = dbConnector.getEmail(userName);
		System.out.println(email + " " + email1);
		assertArrayEquals(email.toCharArray(), email1.toCharArray());
	}
	
	@Test public void testGetSubscriberEmails()
	{
		try {
			dbConnector.subscribeToBusiness(userName, reviewerPassword, businessName);
		} catch (InvalidReviewerAuthenticationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		String[] emails = dbConnector.getSubscriberEmails(businessName);
		assertFalse(emails.length == 0);
	}
	
	@Test public void testGetReviewerInfo()
	{
		try {
			dbConnector.subscribeToBusiness(userName, reviewerPassword, businessName);
			Reviewer rev = dbConnector.getReviewerInfo(userName, reviewerPassword);
			assertFalse(rev == null);
		} catch (InvalidReviewerAuthenticationException e) {
			e.printStackTrace();
		}
		
		try {
			Reviewer rev = dbConnector.getReviewerInfo(userName, "wrong pass");
			fail();
		} catch (InvalidReviewerAuthenticationException e) {
			e.printStackTrace();
		}
	}
}
